package com.css.upms.biz.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.css.common.core.constent.CommonConstant;
import com.css.common.core.datascope.DataScope;
import com.css.common.core.utils.R;
import com.css.common.core.utils.UUIDUtils;
import com.css.common.security.utils.SecurityUtil;
import com.css.upms.api.dto.DeptTree;
import com.css.upms.api.entity.SysDept;
import com.css.upms.api.entity.SysRoleDept;
import com.css.upms.api.entity.SysUser;
import com.css.upms.api.entity.SysUserDept;
import com.css.upms.api.vo.TreeUtil;
import com.css.upms.biz.mapper.SysDeptMapper;
import com.css.upms.biz.mapper.SysRoleDeptMapper;
import com.css.upms.biz.mapper.SysUserMapper;
import com.css.upms.biz.service.SysDeptService;
import com.css.upms.biz.service.SysUserDeptService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 部门信息表
 *
 * @author hanyx
 * @date 2019-05-03 01:56:29
 */
@Slf4j
@Service("sysDeptService")
@AllArgsConstructor
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements SysDeptService {

    private final SysRoleDeptMapper sysRoleDeptMapper;
    private final SysUserMapper sysUserMapper;
    private final SysUserDeptService sysUserDeptService;

    /**
     * 部门信息表简单分页查询
     *
     * @param sysDept 部门信息表
     * @return
     */
    @Override
    public IPage<SysDept> getSysDeptPage(Page<SysDept> page, SysDept sysDept) {
        // 配置数据权限
        DataScope dataScope = this.getDataScope(SecurityUtil.getUser().getId());
        return baseMapper.getSysDeptPage(page, sysDept, dataScope);
    }


    /**
     * 查询全部部门树
     *
     * @return 树
     */
    @Override
    public List<DeptTree> listDeptTrees() {
        return getDeptTree(selectAllValid(), CommonConstant.ROOT_NODE_VAL);
    }

    @Override
    public List<DeptTree> listDataScopeTrees() {
        SysUser sysUser = sysUserMapper.selectById(SecurityUtil.getUser().getId());
        return getDeptTree(getSysDeptList(new SysDept()), this.getById(sysUser.getDeptId()).getParentId());
    }

    /**
     * 查询用户部门树
     *
     * @return
     */
    @Override
    public List<DeptTree> listCurrentUserDeptTrees() {
        return listCurrentUserDeptTrees(Boolean.FALSE);
    }

    @Override
    public List<DeptTree> listCurrentUserDeptTrees(Boolean parentFlag) {
        String currentDeptId = sysUserMapper.selectById(SecurityUtil.getUser().getId()).getDeptId();
        return listUserDeptTrees(currentDeptId, parentFlag);
    }

    /**
     * 查询指定用户部门树
     *
     * @param userId
     * @return
     */
    @Override
    public List<DeptTree> listDeptTreesByUserId(String userId) {
        SysUser sysUser = sysUserMapper.selectById(userId);
        if (sysUser != null) {
            return listUserDeptTrees(sysUser.getDeptId(), Boolean.FALSE);
        }
        return null;
    }

    private List<DeptTree> listUserDeptTrees(String deptId, Boolean parentFlag) {

        List<DeptTree> resultTree = new ArrayList<>();
        SysDept sysDept = baseMapper.selectById(deptId);

        DeptTree currentDeptTree = new DeptTree();
        currentDeptTree.setParentId(sysDept.getParentId());
        currentDeptTree.setTitle(sysDept.getDeptName());
        currentDeptTree.setName(sysDept.getDeptName());
        currentDeptTree.setId(deptId);
        currentDeptTree.setStatus(sysDept.getStatus());
        resultTree.add(currentDeptTree);

        List<String> idList = childDeptIds(deptId);
        if (CollectionUtils.isNotEmpty(idList)) {
            List<SysDept> deptList = baseMapper.selectBatchIds(idList);
            List<DeptTree> subTree = getDeptTree(deptList, deptId);
            for (DeptTree vo : subTree) {
                currentDeptTree.add(vo);
            }
        }

        /**
         * 是否添加父节点, 部门编辑树展示需要
         */
        if (parentFlag) {
            if (!StringUtils.equals(CommonConstant.ROOT_NODE_VAL, sysDept.getParentId())) {
                SysDept parentDept = baseMapper.selectById(sysDept.getParentId());
                DeptTree parentDeptTree = new DeptTree();
                parentDeptTree.setParentId(parentDept.getParentId());
                parentDeptTree.setTitle(parentDept.getDeptName());
                parentDeptTree.setName(parentDept.getDeptName());
                parentDeptTree.setId(parentDept.getDeptId());
                parentDeptTree.setStatus(parentDept.getStatus());
                parentDeptTree.add(currentDeptTree);
                resultTree = new ArrayList<>();
                resultTree.add(parentDeptTree);
            }
        }
        return resultTree;
    }


    /**
     * 添加信息部门
     *
     * @param dept 部门
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R saveDept(SysDept dept) {
        String deptCode = dept.getDeptCode();
        if (StringUtils.isNotBlank(deptCode)) {
            SysDept vo = baseMapper.selectOne(Wrappers.<SysDept>query().lambda().eq(SysDept::getDeptCode, deptCode));
            if (vo != null) {
                return R.buildError("部门编码已存在");
            }
        } else {
            return R.buildError("部门编码不能为空.");
        }

        if (StringUtils.isBlank(dept.getDeptId())) {
            dept.setDeptId(UUIDUtils.get32UUID());
        }

        if (StringUtils.isNotBlank(dept.getParentId()) && StringUtils.equals(dept.getDeptId(), dept.getParentId())) {
            return R.buildError("上级部门不能是自己.");
        }
        dept.setCreateTime(LocalDateTime.now());
        dept.setCreateBy(SecurityUtil.getUser().getId());
        return new R(this.save(dept));
    }

    /**
     * 删除部门
     *
     * @param id 部门 ID
     * @return 成功、失败
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R removeDeptById(String id) {
        List<String> deptIds = childDeptIds(id);
        if (CollectionUtils.isNotEmpty(deptIds)) {
            deptIds.add(id);
            return R.buildError("部门含有下级不能删除");
        }
        int userCount = sysUserMapper.selectCount(Wrappers.<SysUser>query().lambda()
                .eq(SysUser::getDeptId, id));
        if (userCount > 0) {
            return R.buildError("部门中存在用户,请先转移用户");
        }
        sysRoleDeptMapper.delete(Wrappers.<SysRoleDept>query()
                .lambda().eq(SysRoleDept::getDeptId, id));
        return R.builder().data(this.removeById(id)).build();
    }

    /**
     * 更新部门
     *
     * @param sysDept 部门信息
     * @return 成功、失败
     */
    @Override
    public R updateDeptById(SysDept sysDept) {
        if (StringUtils.equals(sysDept.getDeptId(), sysDept.getParentId())) {
            return R.buildError("上级部门不能是自己.");
        }
        if (StringUtils.isBlank(sysDept.getParentId())) {
            sysDept.setDeptId(CommonConstant.ROOT_NODE_VAL);
        }
        sysDept.setModifyTime(LocalDateTime.now());
        sysDept.setModifyBy(SecurityUtil.getUser().getId());
        return R.buildSuccess(this.updateById(sysDept));
    }

    /**
     * 有效的部门数据
     *
     * @return
     */
    @Override
    public List<SysDept> selectAllValid() {
        return baseMapper.selectList(Wrappers.<SysDept>query().lambda()
                .eq(SysDept::getDelFlag, CommonConstant.STATUS_NORMAL)
                .eq(SysDept::getStatus, CommonConstant.STATUS_NORMAL)
                .orderByAsc(SysDept::getOrderNum));
    }

    /**
     * 通过角色编号查询数据权限
     *
     * @param roleId 角色ID
     * @return 菜单列表
     */
    @Override
    public List<SysDept> getDeptByRoleId(String roleId) {
        return baseMapper.listDeptsByRoleId(roleId);
    }

    /**
     * 通过用户编号查询数据权限
     *
     * @param userId 角色ID
     * @return 部门列表
     */
    @Override
    public List<SysDept> getDeptByUserId(String userId) {
        return baseMapper.listDeptsByUserId(userId);
    }

    /**
     * 对部门列表做group操作
     *
     * @param voList
     * @return
     */
    private Map<String, List<String>> groupDept(List<SysDept> voList) {
        Map<String, List<String>> parentMap = new HashMap<>();
        if (voList != null && !voList.isEmpty()) {
            for (SysDept vo : voList) {
                String parentId = vo.getParentId();
                List<String> subList = parentMap.get(parentId);
                if (subList == null) {
                    subList = new ArrayList<>();
                    parentMap.put(parentId, subList);
                }
                subList.add(vo.getDeptId());
            }
        }
        return parentMap;
    }

    /**
     * 获取指定部门id的下级部门集合
     *
     * @param deptId 指定部门id
     * @return 级部门集合
     */
    @Override
    public List<String> childDeptIds(String deptId) {
        return childDeptIds(deptId, selectAllValid());
    }

    @Override
    public List<String> childDeptIds(String deptId, List<SysDept> deptList) {
        Set<String> resultSet = new HashSet<>();
        Map<String, List<String>> groupMap = groupDept(deptList);
        if (MapUtils.isNotEmpty(groupMap)) {
            TreeUtil.childNodeIds(deptId, resultSet, groupMap);
            List<String> list = groupMap.get(deptId);
            if (CollectionUtils.isNotEmpty(list)) {
                resultSet.addAll(list);
            }
        }
        return new ArrayList<>(resultSet);
    }

    @Override
    public DataScope getDataScope(String userId) {
        DataScope dataScope = new DataScope();
        List<SysUserDept> sysUserDepts = sysUserDeptService.list(Wrappers.<SysUserDept>query().lambda().eq(SysUserDept::getUserId, userId));
        String currentDeptId = sysUserMapper.selectById(SecurityUtil.getUser().getId()).getDeptId();
        // 配置过数据权限
        if (CollectionUtils.isNotEmpty(sysUserDepts)) {
            dataScope.setDeptIds(sysUserDepts.stream().map(userDept -> userDept.getDeptId()).collect(Collectors.toList()));
            dataScope.getDeptIds().add(currentDeptId);
        } else { // 没有设置数据权限
            // 默认查询当前机构及下级机构数据权权限
            List<String> reusult = new ArrayList<>();
            List<String> childDeptIds = this.childDeptIds(currentDeptId);
            if (CollectionUtils.isNotEmpty(childDeptIds)) {
                reusult.addAll(childDeptIds);
            }
            reusult.add(currentDeptId);
            dataScope.setDeptIds(reusult);
        }
        return dataScope;
    }

    /**
     * 构建部门树
     *
     * @param depts 部门
     * @return
     */
    private List<DeptTree> getDeptTree(List<SysDept> depts, String rootNodeVal) {
        List<DeptTree> treeList = depts.stream()
                .filter(dept -> !dept.getDeptId().equals(dept.getParentId()))
                .map(dept -> TreeUtil.parseDetpTree(dept)).collect(Collectors.toList());
        return TreeUtil.buildByRecursive(treeList, rootNodeVal);
    }

    /**
     * 判断指定节点是不是当前登录用户的子节点
     *
     * @param deptId
     * @return
     */
    @Override
    public Boolean modifyCheck(String deptId) {
        String currentDeptId = sysUserMapper.selectById(SecurityUtil.getUser().getId()).getDeptId();
        if (StringUtils.equals(deptId, currentDeptId)) {
            return Boolean.FALSE;
        }
        Boolean modifyFlag = Boolean.FALSE;
        List<String> childList = this.childDeptIds(currentDeptId);
        for (String childId : childList) {
            if (StringUtils.equals(deptId, childId)) {
                modifyFlag = Boolean.TRUE;
            }
        }
        return modifyFlag;
    }

    /**
     * 无分页的列表查询
     *
     * @param sysDept
     * @return
     */
    @Override
    public List<SysDept> getSysDeptList(SysDept sysDept) {
        if (sysDept == null) {
            return new ArrayList<SysDept>();
        }
        // 配置数据权限
        DataScope dataScope = this.getDataScope(SecurityUtil.getUser().getId());
        return baseMapper.getSysDeptList(sysDept, dataScope);
    }
}